package org.smile.auth.test;


import io.jsonwebtoken.*;
import io.jsonwebtoken.impl.Base64Codec;
import org.smile.util.DateUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
   static int access_token_expiration=100000;
    public static void main(String[] args) {
        // Press Alt+Enter with your caret at the highlighted text to see how
        // IntelliJ IDEA suggests fixing it.

        testJwt();
        System.out.println(generateJwtToken());
        testParseToken();

    }

    /** 测试生成token1 */
    public static void testJwt() {
        JwtBuilder jwtBuilder = Jwts.builder()
                // 唯一ID {"":""}
                .setId("888")
                // 接受的用户 {"sub":"Rose"}
                .setSubject("Rose")
                // 签发时间 {"iat":"。。。"}
                .setIssuedAt(new Date())
                // 签名算法 及秘钥
                .signWith(SignatureAlgorithm.HS256, "aVBhbkUxcEEyc1dvMmRCeVpM");
        // 签发token
        String token = jwtBuilder.compact();
        System.out.println(token);

        String[] split = token.split("\\.");
        // 头部
        System.out.println(Base64Codec.BASE64.decodeToString(split[0]));
        // 载荷
        System.out.println(Base64Codec.BASE64.decodeToString(split[1]));
        // 算法及秘钥 这个会乱码
        System.out.println(Base64Codec.BASE64.decodeToString(split[2]));

    }
    /** 测试生成token2 */
    public static String generateJwtToken(){

        // 头部 map / Jwt的头部承载，第一部分
        // 可不设置 默认格式是{"alg":"HS256"}
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");


        //载荷 map / Jwt的载荷，第二部分
        Map<String,Object> claims = new HashMap<String,Object>();

        //私有声明 / 自定义数据，根据业务需要添加
        claims.put("id","123456");
        claims.put("userName", "admin");

        //标准中注册的声明 (建议但不强制使用)
        //一旦写标准声明赋值之后，就会覆盖了那些标准的声明
        claims.put("iss", "xt");
            /*    iss: jwt签发者
                sub: jwt所面向的用户
                aud: 接收jwt的一方
                exp: jwt的过期时间，这个过期时间必须要大于签发时间
                nbf: 定义在什么时间之前，该jwt都是不可用的.
                iat: jwt的签发时间
                jti: jwt的唯一身份标识，主要用来作为一次性token,从而回避重放攻击
            */

        //下面就是在为payload添加各种标准声明和私有声明了
        return Jwts.builder() // 这里其实就是new一个JwtBuilder，设置jwt的body
                .setHeader(map)         // 头部信息
                .setClaims(claims)      // 载荷信息
                .setId(UUID.randomUUID().toString()) // 设置jti(JWT ID)：是JWT的唯一标识，从而回避重放攻击。
                .setIssuedAt(new Date())       // 设置iat: jwt的签发时间
                .setExpiration(new Date(System.currentTimeMillis() + access_token_expiration * 1000)) // 设置exp：jwt过期时间
                .setSubject("小团")    //设置sub：代表这个jwt所面向的用户，所有人
                .signWith(SignatureAlgorithm.HS256, "aVBhbkUxcEEyc1dvMmRCeVpM")//设置签名：通过签名算法和秘钥生成签名
                .compact(); // 开始压缩为xxxxx.yyyyy.zzzzz 格式的jwt token
    }

    /** 解析token */
    public static void testParseToken() {
        String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiLlsI_lm6IiLCJpc3MiOiJ4dCIsImlkIjoiMTIzNDU2IiwidXNlck5hbWUiOiJhZG1pbiIsImV4cCI6MTcyNTg5NTkyNiwiaWF0IjoxNzI1Nzk1OTI2LCJqdGkiOiIxZGUxZjY5MS04YjRhLTQ1N2MtOTBjNC01ZjBkZGNmNWFmMTcifQ.1e4aAn4JSXJTDiQvD-4POyNUF7tzZS94iNo3mabRTjo";
        //得到的是荷载
        Claims claims = (Claims) Jwts.parser()
                // 解析时的秘钥一定要和签发时秘钥相同，但是发现这了的秘钥为4-7个x都是可以成功解析的
                .setSigningKey("aVBhbkUxcEEyc1dvMmRCeVpM111")
                // .parse(token)
                .parseClaimsJws(token)
                .getBody();
        System.out.println(claims);
        System.out.println(DateUtils.defaultFormat(claims.getExpiration()));
        // 得到的是头部
        JwsHeader test = Jwts.parser()
                // 解析时的秘钥一定要和签发时秘钥相同，但是发现这了的秘钥为4-7个x都是可以成功解析的
                .setSigningKey("aVBhbkUxcEEyc1dvMmRCeVpM111")
                // .parse(token)
                .parseClaimsJws(token)
                .getHeader();
        System.out.println(test);
    }
}
